package com.zp.self.module.简单的login;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 参考：https://blog.csdn.net/maoliran/article/details/51841420
 * 当客户端（浏览器）收到带有类似“WWW-Authenticate: Basic realm=“.””的信息后，将会弹出一个对话框，要求用户输入验证信息。
 *
 * 使用www-authenticate认证的优缺点
 * 优点：使用www-authenticate认证，在服务端做的事情较少，有一部分验证处理都是在客户端的浏览器完成的。像是否需要二次输入用户信息，弹出怎样的用户信息对话框，这些都是浏览器做的事，服务端并不需要再编写用户对话框之类的东西，也不需要判断客户端IP是否是同一个。
 * 缺点：验证方式太简单，容易被破解。
 *
 * @author ：yuelin.yin@rootcloud.com
 * @date ：Created in 2020/9/8 10:47
 * @description：
 * @modified By：
 */
@Slf4j
//@Component
@WebFilter(filterName = "initialContexFilter", urlPatterns = "/userManagement/api/*")
public class InitialContexFilter implements Filter {

    public  static final String oauthPre ="Basic ";

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        if (request.getMethod().toUpperCase().equals("OPTIONS")) {
            isOptions(servletRequest, servletResponse, filterChain, response);
            return;
        }
        if (!checkHeaderAuth(request, response)){
            continueInput(response);
            return;
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }



    /**
     * 校验令牌 Authorization
     * @param
     * @return
     * @author ZengPeng
     * @date 21:23
     **/
    private boolean checkHeaderAuth(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String auth = request.getHeader("Authorization");
        if (auth == null) {
            log.info("当前莫得令牌...(⊙_⊙)？");
            return false;
        }
        auth = auth.substring(oauthPre.length());
        log.info("打印当前的认证信息auth："+auth);
        String decodedAuth = getFromBASE64(auth);
        log.info("解码认证信息认证信息auth："+decodedAuth);

        if (decodedAuth == null || !decodedAuth.contains(":")) {
            log.info("解码失败！" );
            return false;
        }
        String userName = decodedAuth.split(":")[0];
        String passWord = decodedAuth.split(":")[1];
        if (!verifyLogin(userName, passWord)) {
            log.info("用户认证失败...(⊙_⊙)？");
            return false;
        }
        request.setAttribute("userName", userName);
        log.info("登录成功..." + userName);
        return true;
    }

    /**
     * 没有token
     *
     * @param
     * @return
     * @author ZengPeng
     * @date 21:26
     **/
    private static void continueInput(HttpServletResponse response) {
        response.setStatus(401);
        response.setHeader("Cache-Control", "no-store");
        response.setDateHeader("Expires", 0);
        //WWW-Authenticate的头字段，可以用于实现登录验证,它是在RFC 2617中定义的。
        //这种认证方式在传输过程中是明码传输的，采用的用户名密码加密方式为BASE-64，其解码过程非常简单
        response.setHeader("WWW-authenticate", "Basic Realm=\"RootCloud@keakon.cn\"");
        log.info("不好意思，你还没有权限...不能让你访问哦！");
    }

    /**
     * 验证账户密码
     *
     * @param
     * @return
     * @author ZengPeng
     * @date 21:33
     **/
    private boolean verifyLogin(String userName, String passWord) {
        log.info("认证用户啦！name=" + userName + ",password=" + passWord);
        return userName.equals("zengpeng") && passWord.equals("123456");
    }

    /**
     * 将字符串转换为base64
     *
     * @param
     * @return
     * @author ZengPeng
     * @date 21:32
     **/
    private String getFromBASE64(String s) {
        log.info("当前的BASE64为：" + s);
        if (s == null) return null;
//        BASE64Decoder decoder = new BASE64Decoder();
        try {
            byte[] b = null;//decoder.decodeBuffer(s);
            return new String(b);
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }
    /**
     * isOptions 的操作
     *
     * @param
     * @return
     * @author ZengPeng
     * @date 21:23
     **/
    private void isOptions(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain, HttpServletResponse response) throws IOException, ServletException {
        log.info("进入到了OPTIONS...");
        response.setHeader("Access-Control-Allow-Origin", response.getHeader("Origin"));
        response.addHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, x-requested-with, X-Custom-Header, Request-Ajax");
        filterChain.doFilter(servletRequest, servletResponse);
    }
}
